<template>
  <div class="sokoban-container">
    <div class="game-header">
      <h1>推箱子游戏</h1>
      <div class="level-info">
        <span>关卡: {{ levelNumber }} / {{ totalLevels }}</span>
        <span>步数: {{ moveCount }}</span>
        <button @click="resetLevel" class="reset-btn">重置关卡 (R)</button>
      </div>
    </div>

    <div class="game-content">
      <div class="game-sidebar">
        <!-- 关卡选择器 -->
        <div class="level-categories">
          <div class="level-category">
            <h3>预设关卡</h3>
            <div class="level-selector">
              <button
                v-for="index in 16"
                :key="index"
                :class="[
                  'level-btn',
                  {
                    current: index - 1 === currentLevel,
                    locked: index - 1 > unlockedLevels,
                  },
                ]"
                @click="selectLevel(index - 1)"
                :disabled="index - 1 > unlockedLevels"
              >
                {{ index }}
              </button>
            </div>
          </div>

          <div class="level-category">
            <h3>自定义关卡</h3>
            <div class="level-selector">
              <button
                v-for="(level, index) in customLevels"
                :key="'custom-' + index"
                :class="[
                  'level-btn',
                  {
                    current: index + levels.length === currentLevel,
                  },
                ]"
                @click="selectCustomLevel(index)"
              >
                {{ index + 1 }}
              </button>
            </div>
            <div class="custom-level-controls">
              <button
                @click="showCustomLevelDialog = true"
                class="add-level-btn"
              >
                添加自定义关卡
              </button>
            </div>
          </div>
        </div>

        <!-- 游戏说明 -->
        <div class="game-instructions">
          <h3>游戏说明：</h3>
          <p>使用方向键或WASD移动角色，将所有箱子推到目标点上即可过关。</p>
          <p>按R键可重置当前关卡。</p>
          <div class="legend">
            <div class="legend-item">
              <span class="preview-player"></span>
              <span>玩家</span>
            </div>
            <div class="legend-item">
              <span class="preview-box"></span>
              <span>箱子</span>
            </div>
            <div class="legend-item">
              <span class="preview-target"></span>
              <span>目标点</span>
            </div>
            <div class="legend-item">
              <span class="preview-box-on-target"></span>
              <span>已放好的箱子</span>
            </div>
            <div class="legend-item">
              <span class="preview-wall"></span>
              <span>墙</span>
            </div>
          </div>
        </div>
      </div>

      <div class="game-main">
        <canvas
          ref="gameCanvas"
          width="600"
          height="600"
          class="game-canvas"
        ></canvas>
      </div>
    </div>

    <!-- 自定义关卡对话框 -->
    <div v-if="showCustomLevelDialog" class="custom-level-dialog">
      <div class="dialog-content">
        <h2>添加自定义关卡</h2>
        <div class="custom-level-editor">
          <div class="editor-tools">
            <button
              v-for="tool in editorTools"
              :key="tool.type"
              :class="['tool-btn', { active: currentTool === tool.type }]"
              @click="selectTool(tool.type)"
            >
              <span :class="tool.class"></span>
              {{ tool.name }}
            </button>
          </div>
          <div class="editor-grid" ref="editorGrid">
            <div v-for="(row, y) in editorMap" :key="y" class="editor-row">
              <div
                v-for="(cell, x) in row"
                :key="x"
                :class="['editor-cell', getCellClass(cell)]"
                @click="handleCellClick(x, y)"
                @mouseover="handleCellHover(x, y, $event)"
              ></div>
            </div>
          </div>
          <div class="editor-controls">
            <button @click="clearEditor" class="clear-btn">清空</button>
            <button
              @click="saveCustomLevel"
              class="save-btn"
              :disabled="!isValidLevel"
            >
              保存关卡
            </button>
            <button @click="showCustomLevelDialog = false" class="cancel-btn">
              取消
            </button>
          </div>
        </div>
      </div>
    </div>

    <div v-if="isGameWon && !isAllLevelsCompleted" class="game-message">
      <div class="message-content">
        <h2>恭喜过关！</h2>
        <p>你用了 {{ moveCount }} 步完成了本关卡</p>
        <button @click="nextLevel" class="next-level-btn">进入下一关</button>
      </div>
    </div>

    <div v-if="isAllLevelsCompleted" class="game-message">
      <div class="message-content">
        <h2>恭喜你通关了所有关卡！</h2>
        <p>你用了 {{ moveCount }} 步完成了最后一关</p>
        <button @click="resetGame" class="reset-game-btn">重新开始</button>
      </div>
    </div>
  </div>
</template>

<script>
import { ref, onMounted, onUnmounted, watch, computed } from 'vue';
import { useGameLogic, levels } from '../composables/useGameLogic';

export default {
  name: 'SokobanGame',
  setup() {
    const gameCanvas = ref(null);
    const ctx = ref(null);
    const cellSize = ref(40);

    // 使用游戏逻辑组合式函数
    const {
      gameMap,
      playerPosition,
      levelNumber,
      totalLevels,
      isGameWon,
      isAllLevelsCompleted,
      initLevel,
      handleKeyDown,
      nextLevel,
      resetLevel,
      resetGame,
      currentLevel,
      moveCount,
      unlockedLevels,
      selectLevel,
      getLevelData,
      addCustomLevel: addCustomLevelToGame,
      getCustomLevels,
      deleteCustomLevel,
      getAllLevels,
    } = useGameLogic();

    // 自定义关卡相关
    const showCustomLevelDialog = ref(false);
    const customLevelInput = ref('');
    const customLevels = ref([]);

    // 加载自定义关卡
    const loadCustomLevels = () => {
      const oldLength = customLevels.value.length;
      customLevels.value = getCustomLevels();
      console.log('加载自定义关卡:', customLevels.value);

      // 如果自定义关卡数量发生变化，重新绘制游戏
      if (oldLength !== customLevels.value.length) {
        console.log('自定义关卡数量变化，重新绘制游戏');
        drawGame();
      }

      return customLevels.value;
    };

    // 添加自定义关卡
    const addCustomLevel = () => {
      try {
        const levelData = customLevelInput.value
          .trim()
          .split(',')
          .map((row) => row.trim())
          .filter((row) => row.length > 0);

        if (addCustomLevelToGame(levelData)) {
          loadCustomLevels();
          showCustomLevelDialog.value = false;
          customLevelInput.value = '';
        } else {
          alert('添加关卡失败，请检查关卡格式是否正确');
        }
      } catch (error) {
        alert('添加关卡失败：' + error.message);
      }
    };

    // 编辑器相关
    const editorMap = ref(
      Array(9)
        .fill()
        .map(() => Array(9).fill(' '))
    );
    const currentTool = ref('wall');
    const isMouseDown = ref(false);

    const editorTools = [
      { type: 'wall', name: '墙', class: 'preview-wall' },
      { type: 'player', name: '玩家', class: 'preview-player' },
      { type: 'box', name: '箱子', class: 'preview-box' },
      { type: 'target', name: '目标点', class: 'preview-target' },
      { type: 'empty', name: '空地', class: 'preview-empty' },
    ];

    // 选择编辑工具
    const selectTool = (tool) => {
      currentTool.value = tool;
    };

    // 处理单元格点击
    const handleCellClick = (x, y) => {
      if (currentTool.value === 'player') {
        // 移除旧的玩家位置
        for (let i = 0; i < editorMap.value.length; i++) {
          for (let j = 0; j < editorMap.value[i].length; j++) {
            if (editorMap.value[i][j] === '@') {
              editorMap.value[i][j] = ' ';
            }
          }
        }
      }

      const cellMap = {
        wall: '#',
        player: '@',
        box: '$',
        target: '.',
        empty: ' ',
      };

      editorMap.value[y][x] = cellMap[currentTool.value];
    };

    // 处理单元格悬停
    const handleCellHover = (x, y, event) => {
      if (event.buttons === 1) {
        // 鼠标左键按下
        handleCellClick(x, y);
      }
    };

    // 清空编辑器
    const clearEditor = () => {
      editorMap.value = Array(9)
        .fill()
        .map(() => Array(9).fill(' '));
    };

    // 检查关卡是否有效
    const isValidLevel = computed(() => {
      let hasPlayer = false;
      let boxCount = 0;
      let targetCount = 0;

      for (const row of editorMap.value) {
        for (const cell of row) {
          if (cell === '@') hasPlayer = true;
          if (cell === '$') boxCount++;
          if (cell === '.') targetCount++;
        }
      }

      return hasPlayer && boxCount > 0 && boxCount === targetCount;
    });

    // 保存自定义关卡
    const saveCustomLevel = () => {
      if (!isValidLevel.value) {
        alert(
          '关卡无效！请确保：\n1. 有一个玩家\n2. 箱子数量等于目标点数量\n3. 至少有一个箱子和目标点'
        );
        return;
      }

      const levelData = editorMap.value.map((row) => row.join(''));
      console.log('准备保存自定义关卡:', levelData);

      if (addCustomLevelToGame(levelData)) {
        console.log('自定义关卡保存成功');
        loadCustomLevels();
        showCustomLevelDialog.value = false;
        clearEditor();

        // 选择新添加的关卡
        const newLevelIndex = levels.length + customLevels.value.length - 1;
        console.log('新关卡索引:', newLevelIndex);

        // 直接设置当前关卡并初始化，而不是通过selectLevel
        currentLevel.value = newLevelIndex;
        initLevel();
      } else {
        alert('保存关卡失败，请检查关卡格式是否正确');
      }
    };

    // 获取单元格的样式类
    const getCellClass = (cell) => {
      const classMap = {
        '#': 'preview-wall',
        '@': 'preview-player',
        $: 'preview-box',
        '.': 'preview-target',
        ' ': 'preview-empty',
      };
      return classMap[cell];
    };

    // 绘制游戏地图
    const drawGame = () => {
      if (!ctx.value) return;

      // 清空画布
      ctx.value.clearRect(
        0,
        0,
        gameCanvas.value.width,
        gameCanvas.value.height
      );

      // 计算偏移量，使地图居中
      const offsetX =
        (gameCanvas.value.width - gameMap[0].length * cellSize.value) / 2;
      const offsetY =
        (gameCanvas.value.height - gameMap.length * cellSize.value) / 2;

      // 绘制地图
      for (let y = 0; y < gameMap.length; y++) {
        for (let x = 0; x < gameMap[y].length; x++) {
          const cellX = offsetX + x * cellSize.value;
          const cellY = offsetY + y * cellSize.value;

          // 绘制背景（所有单元格都有浅灰色背景）
          ctx.value.fillStyle = '#f0f0f0';
          ctx.value.fillRect(cellX, cellY, cellSize.value, cellSize.value);

          // 根据单元格类型绘制不同内容
          switch (gameMap[y][x]) {
            case '#': // 墙
              ctx.value.fillStyle = '#8B4513'; // 棕色
              ctx.value.fillRect(cellX, cellY, cellSize.value, cellSize.value);
              break;

            case '.': // 目标点
              ctx.value.fillStyle = '#FFD700'; // 金色
              ctx.value.beginPath();
              ctx.value.arc(
                cellX + cellSize.value / 2,
                cellY + cellSize.value / 2,
                cellSize.value / 6,
                0,
                Math.PI * 2
              );
              ctx.value.fill();
              break;

            case '@': // 玩家
              ctx.value.fillStyle = '#4169E1'; // 蓝色
              ctx.value.beginPath();
              ctx.value.arc(
                cellX + cellSize.value / 2,
                cellY + cellSize.value / 2,
                cellSize.value / 2 - 5,
                0,
                Math.PI * 2
              );
              ctx.value.fill();
              break;

            case '+': // 玩家在目标点上
              // 先绘制目标点
              ctx.value.fillStyle = '#FFD700';
              ctx.value.beginPath();
              ctx.value.arc(
                cellX + cellSize.value / 2,
                cellY + cellSize.value / 2,
                cellSize.value / 6,
                0,
                Math.PI * 2
              );
              ctx.value.fill();

              // 再绘制玩家
              ctx.value.fillStyle = '#4169E1';
              ctx.value.beginPath();
              ctx.value.arc(
                cellX + cellSize.value / 2,
                cellY + cellSize.value / 2,
                cellSize.value / 2 - 5,
                0,
                Math.PI * 2
              );
              ctx.value.fill();
              break;

            case '$': // 箱子
              ctx.value.fillStyle = '#A52A2A'; // 褐色
              ctx.value.fillRect(
                cellX + 5,
                cellY + 5,
                cellSize.value - 10,
                cellSize.value - 10
              );
              break;

            case '*': // 箱子在目标点上
              // 先绘制目标点
              ctx.value.fillStyle = '#FFD700';
              ctx.value.beginPath();
              ctx.value.arc(
                cellX + cellSize.value / 2,
                cellY + cellSize.value / 2,
                cellSize.value / 6,
                0,
                Math.PI * 2
              );
              ctx.value.fill();

              // 再绘制箱子（绿色表示已放好）
              ctx.value.fillStyle = '#32CD32'; // 绿色
              ctx.value.fillRect(
                cellX + 5,
                cellY + 5,
                cellSize.value - 10,
                cellSize.value - 10
              );
              break;
          }

          // 绘制单元格边框
          ctx.value.strokeStyle = '#ccc';
          ctx.value.strokeRect(cellX, cellY, cellSize.value, cellSize.value);
        }
      }
    };

    // 监听游戏地图变化，重新绘制
    watch(
      gameMap,
      () => {
        drawGame();
      },
      { deep: true }
    );

    // 监听游戏获胜状态
    watch(isGameWon, (newVal) => {
      if (newVal) {
        console.log('恭喜过关！');
      }
    });

    // 监听自定义关卡变化
    watch(
      customLevels,
      () => {
        console.log('自定义关卡已更新:', customLevels.value);
      },
      { deep: true }
    );

    // 选择自定义关卡
    const selectCustomLevel = (index) => {
      console.log('选择自定义关卡:', index, '总预设关卡数:', levels.length);
      const levelIndex = index + levels.length;
      console.log('计算后的关卡索引:', levelIndex);
      console.log('当前自定义关卡数据:', customLevels.value[index]);

      // 确保关卡数据存在
      if (!customLevels.value[index]) {
        console.error('自定义关卡数据不存在:', index);
        return;
      }

      const result = selectLevel(levelIndex);
      console.log('选择关卡结果:', result);

      // 如果选择失败，尝试强制初始化
      if (!result) {
        console.log('尝试强制初始化关卡');
        currentLevel.value = levelIndex;
        initLevel();
      }
    };

    // 组件挂载时初始化
    onMounted(() => {
      ctx.value = gameCanvas.value.getContext('2d');
      drawGame();
      window.addEventListener('keydown', handleKeyDown);

      // 加载自定义关卡
      loadCustomLevels();
      console.log('初始化完成，自定义关卡数量:', customLevels.value.length);
    });

    // 组件卸载时清理
    onUnmounted(() => {
      window.removeEventListener('keydown', handleKeyDown);
    });

    return {
      gameCanvas,
      levelNumber,
      totalLevels,
      isGameWon,
      isAllLevelsCompleted,
      resetLevel,
      nextLevel,
      resetGame,
      moveCount,
      unlockedLevels,
      selectLevel,
      selectCustomLevel,
      showCustomLevelDialog,
      customLevels,
      customLevelInput,
      addCustomLevel,
      editorMap,
      currentTool,
      editorTools,
      selectTool,
      handleCellClick,
      handleCellHover,
      clearEditor,
      saveCustomLevel,
      isValidLevel,
      getCellClass,
      currentLevel,
      levels,
    };
  },
};
</script>

<style scoped>
.sokoban-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 20px;
  font-family: 'Microsoft YaHei', Arial, sans-serif;
  max-width: 1200px;
  margin: 0 auto;
  background-color: #f8f9fa;
  border-radius: 15px;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}

.game-header {
  text-align: center;
  margin-bottom: 30px;
  width: 100%;
  padding: 20px;
  background: linear-gradient(135deg, #4caf50, #2196f3);
  border-radius: 12px;
  color: white;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.game-header h1 {
  margin: 0;
  font-size: 2.5em;
  text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2);
}

.level-info {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 20px;
  width: 100%;
  margin: 15px auto 0;
  font-size: 1.2em;
}

.level-info span {
  background-color: rgba(255, 255, 255, 0.2);
  padding: 8px 15px;
  border-radius: 20px;
}

.game-content {
  display: flex;
  width: 100%;
  gap: 30px;
  margin-top: 20px;
}

.game-sidebar {
  flex: 0 0 320px;
  display: flex;
  flex-direction: column;
  gap: 25px;
}

.game-main {
  flex: 1;
  display: flex;
  justify-content: center;
  align-items: flex-start;
}

.game-canvas {
  border: 3px solid #333;
  border-radius: 12px;
  background-color: #ffffff;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
}

.game-message {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.7);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 10;
}

.message-content {
  background-color: white;
  padding: 30px;
  border-radius: 10px;
  text-align: center;
}

button {
  padding: 10px 15px;
  border: none;
  border-radius: 5px;
  cursor: pointer;
  font-size: 16px;
  margin: 5px;
  transition: background-color 0.3s;
}

.reset-btn {
  background: linear-gradient(145deg, #f44336, #d32f2f);
  color: white;
  padding: 10px 20px;
  border-radius: 25px;
  font-weight: bold;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
  transition: all 0.3s ease;
}

.reset-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}

.next-level-btn,
.reset-game-btn {
  background-color: #4caf50;
  color: white;
  font-size: 18px;
  padding: 12px 20px;
}

button:hover {
  opacity: 0.9;
}

.game-instructions {
  background-color: white;
  border-radius: 12px;
  padding: 25px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.game-instructions h3 {
  margin: 0 0 20px 0;
  color: #333;
  font-size: 1.3em;
  text-align: center;
  position: relative;
}

.game-instructions h3::after {
  content: '';
  display: block;
  width: 50px;
  height: 3px;
  background: linear-gradient(90deg, #4caf50, #2196f3);
  margin: 8px auto 0;
  border-radius: 2px;
}

.game-instructions p {
  margin: 12px 0;
  color: #555;
  line-height: 1.6;
  font-size: 1.1em;
}

.legend {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 12px;
  margin-top: 20px;
  padding: 15px;
  background-color: #f8f9fa;
  border-radius: 10px;
}

.legend-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  background-color: white;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.legend-item span:first-child {
  width: 30px;
  height: 30px;
  border: 1px solid #ddd;
  display: inline-block;
  border-radius: 4px;
  flex-shrink: 0;
  position: relative;
}

.legend-item span:last-child {
  color: #333;
  font-size: 14px;
  white-space: nowrap;
}

.add-level-btn {
  width: 100%;
  background: linear-gradient(145deg, #2196f3, #1976d2);
  color: white;
  padding: 12px 24px;
  border-radius: 25px;
  font-weight: bold;
  margin-top: 15px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
  transition: all 0.3s ease;
}

.add-level-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}

.custom-level-dialog {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.8);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 20;
  backdrop-filter: blur(5px);
}

.dialog-content {
  background-color: white;
  padding: 30px;
  border-radius: 15px;
  max-width: 600px;
  width: 90%;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
}

.dialog-content h2 {
  text-align: center;
  color: #333;
  margin-bottom: 25px;
  font-size: 1.8em;
}

.editor-tools {
  display: flex;
  gap: 12px;
  margin-bottom: 20px;
  flex-wrap: wrap;
  justify-content: center;
}

.tool-btn {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 15px;
  border: 2px solid #ddd;
  border-radius: 8px;
  background-color: white;
  cursor: pointer;
  transition: all 0.3s ease;
  font-weight: 500;
}

.tool-btn span {
  width: 24px;
  height: 24px;
  display: inline-block;
  border-radius: 4px;
  position: relative;
}

.tool-btn.active {
  border-color: #4caf50;
  background-color: #e8f5e9;
  box-shadow: 0 2px 4px rgba(76, 175, 80, 0.2);
}

.editor-grid {
  display: inline-block;
  padding: 15px;
  background-color: #f8f9fa;
  border-radius: 12px;
  margin: 20px 0;
  border: 2px solid #ddd;
}

.editor-row {
  display: flex;
}

.editor-cell {
  width: 45px;
  height: 45px;
  border: 1px solid #ddd;
  margin: 2px;
  cursor: pointer;
  transition: all 0.2s ease;
  border-radius: 4px;
  position: relative;
}

.editor-cell:hover {
  transform: scale(1.05);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.editor-cell.preview-wall {
  background-color: #8b4513;
  border: none;
}

.editor-cell.preview-player {
  background-color: #4169e1;
  border-radius: 50%;
  border: none;
}

.editor-cell.preview-box {
  background-color: #a52a2a;
  border: none;
}

.editor-cell.preview-target {
  background-color: #f5f5f5;
}

.editor-cell.preview-target::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 12px;
  height: 12px;
  background-color: #ffd700;
  border-radius: 50%;
}

.editor-cell.preview-empty {
  background-color: #f5f5f5;
}

.editor-controls {
  display: flex;
  justify-content: center;
  gap: 15px;
  margin-top: 20px;
}

.clear-btn,
.save-btn,
.cancel-btn {
  padding: 12px 25px;
  border-radius: 25px;
  font-weight: bold;
  transition: all 0.3s ease;
}

.clear-btn {
  background: linear-gradient(145deg, #ff9800, #f57c00);
  color: white;
}

.save-btn {
  background: linear-gradient(145deg, #4caf50, #45a049);
  color: white;
}

.cancel-btn {
  background: linear-gradient(145deg, #9e9e9e, #757575);
  color: white;
}

.clear-btn:hover,
.save-btn:hover,
.cancel-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}

.save-btn:disabled {
  background: linear-gradient(145deg, #cccccc, #bbbbbb);
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

.preview-wall {
  background-color: #8b4513 !important;
  border: none !important;
}

.preview-player {
  background-color: #4169e1 !important;
  border-radius: 50% !important;
  border: none !important;
}

.preview-box {
  background-color: #a52a2a !important;
  border: none !important;
}

.preview-target {
  position: relative !important;
  background-color: #f5f5f5 !important;
}

.preview-target::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 12px;
  height: 12px;
  background-color: #ffd700;
  border-radius: 50%;
}

.preview-box-on-target {
  background-color: #32cd32 !important;
  border: none !important;
}

.preview-empty {
  background-color: #f5f5f5 !important;
}
</style>
